/**
 * Created by henian.xu on 2018/1/10.
 * 公用工具类库
 */
import Vue from 'vue'

class Utils {
    constructor() {
        this.autoIncrement = 0
        this.hasOwnProperty = Object.prototype.hasOwnProperty
    }

    /**
     * 空函数
     */
    emptyFn() {}

    mandatory(name) {
        throw new Error(`Missing parameter ${name}`)
    }

    /**
     * 验证参数必填
     * @param name
     * @param parameter
     */
    /* eslint-disable no-unused-vars */
    required(name, parameter = this.mandatory(name)) {}

    /**
     * 创建不重复的 Id
     * @param prefix
     * @returns {string}
     */
    getUniqueId(prefix = '') {
        this.autoIncrement++
        const cDate = new Date().getTime()
        const offDate = new Date(2010, 1, 1).getTime()
        const offset = cDate - offDate
        return prefix + parseFloat(offset + '').toString(16) + this.autoIncrement
    }

    /**
     * 创建不重复Key
     * @returns {string}
     */
    getKey() {
        // const t  = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'
        const t = 'xxxxxxxx'
        return t.replace(/[xy]/g, function(c) {
            const r = (Math.random() * 16) | 0
            const v = c === 'x' ? r : (r & 0x3) | 0x8
            return v.toString(16)
        })
    }

    /**
     * 判断是否为对象属性
     * @param pattern
     * @param name
     * @returns {boolean}
     */
    matches(pattern, name) {
        if (Array.isArray(pattern)) {
            return pattern.indexOf(name) > -1
        } else if (typeof pattern === 'string') {
            return pattern.split(',').indexOf(name) > -1
        } else if (Object.prototype.toString.call(pattern) === '[object RegExp]') {
            return pattern.test(name)
        }
        return false
    }

    /**
     * 获取页面中的 popup-wrap
     * @returns {Element}
     */
    getPopupWrap(page) {
        let r = Array.prototype.indexOf.call(page.$el.classList, 'page')
        let r2 = Array.prototype.indexOf.call(page.$el.classList, 'pages')
        while (r === -1 && r2 === -1) {
            page = page.$parent
            r = Array.prototype.indexOf.call(page.$el.classList, 'page')
            r2 = Array.prototype.indexOf.call(page.$el.classList, 'pages')
        }
        page = page.$el
        let popupWrap = page.querySelector('.popup-wrap')
        if (!popupWrap) {
            popupWrap = document.createElement('div')
            popupWrap.classList.add('popup-wrap')
            page.appendChild(popupWrap)
        }
        return popupWrap
    }

    /**
     * 加载图片
     * @param src
     * @returns {Promise<any>}
     */
    loadImg(src) {
        return new Promise((resolve, reject) => {
            const img = new Image()
            // 当为线上图片时，需要设置 crossOrigin 属性；
            if (src.indexOf('http') === 0) img.crossOrigin = '*'
            img.onload = () => {
                resolve(img)
            }
            img.onerror = () => {
                reject(img)
            }
            img.src = src
        })
    }

    loadImgs(srcs) {
        const lng = srcs.length
        let count = 0
        const imgs = []
        return new Promise((resolve, reject) => {
            srcs.forEach((item, index) => {
                this.loadImg(item)
                    .then(img => {
                        ++count
                        imgs[index] = img
                        if (count >= lng) {
                            resolve(imgs)
                        }
                    })
                    .catch(_err => {
                        reject(_err)
                    })
            })
        })
    }

    /**
     * 获取剩余时间
     * @param startTime
     * @param endTime
     * @returns {{d: number, h: number, m: number, s: number}}
     */
    getRemainTime(startTime, endTime) {
        startTime = new Date(startTime)
        endTime = new Date(endTime)
        const t = endTime.getTime() - startTime.getTime()
        const r = { d: 0, h: 0, m: 0, s: 0 }
        if (t > 0) {
            r.d = Math.floor(t / 1000 / 3600 / 24)
            r.h = Math.floor((t / 1000 / 60 / 60) % 24)
            r.m = Math.floor((t / 1000 / 60) % 60)
            r.s = Math.floor((t / 1000) % 60)
        }
        for (const k in r) {
            if (r.hasOwnProperty(k)) {
                r[k] = r[k] < 10 ? `0${r[k]}` : `${r[k]}`
            }
        }
        return r
    }

    /**
     * 格式化时间
     * @param time
     * @returns {{d: number, h: number, m: number, s: number}}
     */
    fixedTime(time) {
        const t = +time
        if (isNaN(time)) return {}
        const r = { d: 0, h: 0, m: 0, s: 0 }
        if (t > 0) {
            r.d = Math.floor(t / 1000 / 3600 / 24)
            r.h = Math.floor((t / 1000 / 60 / 60) % 24)
            r.m = Math.floor((t / 1000 / 60) % 60)
            r.s = Math.floor((t / 1000) % 60)
        }
        for (const k in r) {
            if (r.hasOwnProperty(k)) {
                r[k] = r[k] < 10 ? `0${r[k]}` : `${r[k]}`
            }
        }
        return r
    }

    /**
     * 根据路径取对象值
     * @param obj
     * @param path
     * @param strict
     * @returns {{o: *, k: *|string, v: null}}
     */
    getPropByPath(obj, path = '', strict) {
        let tempObj = obj
        path = path.replace(/\[(\w+)\]/g, '.$1')
        path = path.replace(/^\./, '')

        const keyArr = path.split('.')
        let i = 0
        for (let len = keyArr.length; i < len - 1; ++i) {
            if (!tempObj && !strict) break
            const key = keyArr[i]
            if (key in tempObj) {
                tempObj = tempObj[key]
            } else {
                if (strict) {
                    throw new Error('please transfer a valid prop path to form item!')
                }
                break
            }
        }
        return {
            o: tempObj,
            k: keyArr[i],
            v: tempObj ? tempObj[keyArr[i]] : null,
        }
    }

    /**
     * 是否对象属性
     * @param obj
     * @param key
     * @returns {boolean | *}
     */
    hasOwn(obj, key) {
        return this.hasOwnProperty.call(obj, key)
    }

    /**
     * 是否 VNode
     * @param node
     * @returns {boolean|boolean|*}
     */
    isVNode(node) {
        return node !== null && typeof node === 'object' && this.hasOwn(node, 'componentOptions')
    }

    /**
     * 数值格式化
     * @param value
     * @param length
     * @returns {*}
     */
    filterNumber(value, length = 2) {
        if (isNaN(value)) {
            const nArr = (value + '').split('-')
            if (nArr.length === 1) return value
            const rArr = []
            nArr.forEach(item => {
                rArr.push(isNaN(item) ? item : +Number(item).toFixed(length))
            })
            return rArr.join('-')
        } else {
            return +Number(value).toFixed(length)
        }
    }

    makeDataMap(data, map) {
        if (Array.isArray(data)) {
            for (let i = 0, l = data.length; i < l; i++) {
                const item = data[i]
                this.makeDataMap(item, map)
            }
        } else {
            for (const key in map) {
                if (map.hasOwnProperty(key)) {
                    const keyData = map[key]
                    let rawData
                    if (keyData.key) {
                        rawData = data[keyData.key]
                    } else {
                        rawData = data[keyData]
                    }
                    if (rawData === undefined) continue
                    data[key] = rawData
                    if (rawData === null) continue
                    if (Array.isArray(rawData)) {
                        for (let i = 0, l = data[key].length; i < l; i++) {
                            const item = data[key][i]
                            this.makeDataMap(item, keyData.children)
                        }
                    } else {
                        this.makeDataMap(data[key], keyData.children)
                    }
                }
            }
        }
    }
}

export default new Utils()
